package com.exam.api.modules.exampaper.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exam.api.common.cardRecognition.CardRecognitionResult;
import com.exam.api.common.cardRecognition.CardRecognitionService;
import com.exam.api.common.exception.GlobalException;
import com.exam.api.modules.exampaper.domain.TblExamPaper;
import com.exam.api.modules.exampaper.domain.TblExamPaperQuestion;
import com.exam.api.modules.exampaper.domain.TblUserAnswerRecord;
import com.exam.api.modules.exampaper.dto.ExamPaperPageDto;
import com.exam.api.modules.exampaper.dto.ExamPaperSaveDto;
import com.exam.api.modules.exampaper.dto.PatchAnswerItemDto;
import com.exam.api.modules.exampaper.mapper.TblExamPaperMapper;
import com.exam.api.modules.exampaper.mapper.TblUserAnswerRecordMapper;
import com.exam.api.modules.exampaper.service.TblExamPaperQuestionService;
import com.exam.api.modules.exampaper.service.TblExamPaperService;
import com.exam.api.modules.exampaper.service.TblUserAnswerRecordService;
import com.exam.api.modules.exampaper.vo.ExamPaperVO;
import com.exam.api.modules.exampaper.vo.PageExamPaperVO;
import com.exam.api.modules.exampaper.vo.UserReviewAnswerItemVO;
import com.exam.api.modules.exampaper.vo.UserReviewAnswerVO;
import com.exam.api.modules.file.service.TblFileService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 试卷主表服务实现类
 */
@Service
public class TblExamPaperServiceImpl extends ServiceImpl<TblExamPaperMapper, TblExamPaper> implements TblExamPaperService {
    @Resource
    private TblExamPaperQuestionService examPaperQuestionService;
    @Resource
    private TblUserAnswerRecordService userAnswerRecordService;
    @Resource
    private TblUserAnswerRecordMapper userAnswerRecordMapper;
    @Resource
    private CardRecognitionService cardRecognitionService;
    @Resource
    private TblFileService fileService;

    @Override
    @Transactional
    public Long saveExamPaper(ExamPaperSaveDto dto) {
        TblExamPaper newPaper = new TblExamPaper();
        newPaper.setName(dto.getName());
        newPaper.setProductId(dto.getProductId());

        if(Objects.nonNull(dto.getId())){
            //更新
            TblExamPaper paper = getById(dto.getId());
            if(Objects.equals(paper.getStatus(),1)){
                throw new GlobalException("该试卷已发布，请勿修改");
            }

            newPaper.setId(paper.getId());
            updateById(newPaper);

        }else {
            //新增
            save(newPaper);
        }

        examPaperQuestionService.removeByExamPaperId(newPaper.getId());
        dto.getQuestions().forEach(detail->{
            detail.setExamPaperId(newPaper.getId());
        });
        examPaperQuestionService.saveBatch(BeanUtil.copyToList(dto.getQuestions(), TblExamPaperQuestion.class));
        return newPaper.getId();
    }

    @Override
    public IPage<PageExamPaperVO> pageExamPaper(ExamPaperPageDto dto) {
        return baseMapper.pageExamPaper(Page.of(dto.getPageNum(), dto.getPageSize()), dto);
    }

    @Override
    public ExamPaperVO getExamPaperVO(Long id) {
        TblExamPaper examPaper = getById(id);
        List<TblExamPaperQuestion> list = examPaperQuestionService.listByExamPaperId(id);
        ExamPaperVO examPaperVO = BeanUtil.copyProperties(examPaper, ExamPaperVO.class);
        examPaperVO.setQuestions(list);
        return examPaperVO;
    }

    @Override
    @Transactional
    public Long patchAnswer(Long id, List<PatchAnswerItemDto> answerItemList) {
        long stuId = StpUtil.getLoginIdAsLong();

        Long historyCount = userAnswerRecordService.lambdaQuery()
                .eq(TblUserAnswerRecord::getPaperId, id)
                .eq(TblUserAnswerRecord::getUserId, stuId).count();
        if(historyCount > 0){
            throw new GlobalException("请勿重复提交");
        }

        //找到试卷的题目
        List<TblExamPaperQuestion> questions = examPaperQuestionService.listByExamPaperId(id);
        //找到已保存的答案
        List<PatchAnswerItemDto> enabList = answerItemList.stream().filter(item -> StrUtil.isNotEmpty(item.getUrl())).toList();

        //先找到客观题，转为答案列表
        Optional<PatchAnswerItemDto> options = enabList.stream().filter(q -> q.getId() == -1L).findAny();

        List<TblUserAnswerRecord> records = new ArrayList<>();
        questions.forEach(q->{
            TblUserAnswerRecord record = new TblUserAnswerRecord();
            record.setPaperId(id);
            record.setUserId(stuId);
            record.setQuestionId(q.getId());

            if(q.getQuestionType() == 1){
                //客观题
                //从答题列表中找到对应的题目
                PatchAnswerItemDto item = enabList.stream().filter(i -> Objects.equals(i.getId(),Long.valueOf( q.getNo()))).findFirst().orElse(new PatchAnswerItemDto());

                record.setAnswerContent(item.getAnswer());
                record.setScore(BigDecimal.ZERO);
                options.ifPresent(patchAnswerItemDto -> record.setFileUrl(patchAnswerItemDto.getUrl()));

                if(StrUtil.equals(item.getAnswer(),q.getCorrectAnswer())){
                    record.setScore(q.getScore());
                }

            }else {
                //主观题
                //从答题列表中找到对应的题目
                PatchAnswerItemDto item = enabList.stream().filter(i -> Objects.equals(i.getId(), q.getId())).findFirst().orElse(new PatchAnswerItemDto());

                record.setAnswerContent(item.getUrl());
                record.setFileUrl(item.getUrl());
                if(StrUtil.isEmpty(item.getUrl())){
                    //没有图片的提交，直接判0分
                    record.setScore(BigDecimal.ZERO);
                }
            }
            records.add(record);

        });

        if(CollUtil.isNotEmpty(records)){
            userAnswerRecordService.saveBatch(records);
        }
        return id;
    }

    @Override
    public CardRecognitionResult recognition(Long id, String url) {
        List<TblExamPaperQuestion> list = examPaperQuestionService
                .lambdaQuery()
                .eq(TblExamPaperQuestion::getExamPaperId, id)
                .eq(TblExamPaperQuestion::getQuestionType, 1)
                .list();

        Map<String, Object> map = new HashMap<>();
        map.put("image_url", url);
        String execute = HttpUtil.post("http://119.45.170.147:5000/recognize", JSONUtil.toJsonStr(map));
        JSONObject jsonObject = JSONUtil.parseObj(execute);
        Boolean success = jsonObject.getBool("success");

        CardRecognitionResult result = new CardRecognitionResult();
        Map<Integer,String> answers = new HashMap<>();
        if(success){
            JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("answers");
            for (Object o : jsonArray) {
                JSONObject jsonObject1 = (JSONObject) o;
                String answer = jsonObject1.getStr("answer");
                Integer questionNumber = jsonObject1.getInt("question_number");
                answers.put(questionNumber,answer);
            }
        }
        list.forEach(q->{
            CardRecognitionResult.Result r = new CardRecognitionResult.Result();
            r.setNo(q.getNo());
            r.setResult(answers.get(q.getNo()));
            result.getResultList().add(r);
        });
        return result;
//
//        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//        HttpUtil.download( url, outputStream,false);
//        CardRecognitionResult start = cardRecognitionService.start(outputStream,list.size());
//        FileInfo fileInfo = fileService.uploadFile(start.getResultImageArray());
//        start.setImageUrl(fileInfo.getUrl());
//        start.setResultImageArray(null);
//        return start;
    }

    @Override
    public List<PageExamPaperVO> userExamPaperList() {
        return baseMapper.userExamPaperList(StpUtil.getLoginIdAsLong());
    }

    @Override
    public UserReviewAnswerVO getReviewAnswer(Long id) {
        UserReviewAnswerVO vo = new UserReviewAnswerVO();
        List<UserReviewAnswerVO> userReviewAnswerVOS = userAnswerRecordMapper.selectUserScoreAndRank(id, StpUtil.getLoginIdAsLong());
        if(userReviewAnswerVOS.size() == 1){
            vo = userReviewAnswerVOS.get(0);
            List<UserReviewAnswerItemVO> answerItemVOS = userAnswerRecordMapper.selectUserAnswerList(id, StpUtil.getLoginIdAsLong());
            vo.setAnswerItems(answerItemVOS);
            return vo;
        }
        return vo;
    }
}